package common.httpclient;

import common.utils.HttpUtils;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

public class HttpApiClient {

  private final static int DEFAULT_MAX_TOTAL_CONNECTIONS = 1600;
  private final static int DEFAULT_MAX_ROUTE_CONNECTIONS = 200;
  private final static int DEFAULT_CONNECT_REQUEST_TIMEOUT = 100;
  private final static int DEFAULT_CONNECT_TIMEOUT = 100;
  private final static int DEFAULT_READ_TIMEOUT = 900;
  private HttpClient httpClient;
  private int maxTotalConnections;
  private int maxRouteConnections;
  private int connectTimeout;
  private int readTimeout;

  public HttpApiClient(int connectTimeout, int readTimeout) {
    this.connectTimeout = connectTimeout;
    this.readTimeout = readTimeout;
  }

  public HttpApiClient init() {
    if (maxTotalConnections == 0) {
      this.maxTotalConnections = DEFAULT_MAX_TOTAL_CONNECTIONS;
    }
    if (maxRouteConnections == 0) {
      this.maxRouteConnections = DEFAULT_MAX_ROUTE_CONNECTIONS;
    }
    if (connectTimeout == 0) {
      this.connectTimeout = DEFAULT_CONNECT_TIMEOUT;
    }
    if (readTimeout == 0) {
      this.readTimeout = DEFAULT_READ_TIMEOUT;
    }

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
    connectionManager.setMaxTotal(maxTotalConnections);
    connectionManager.setDefaultMaxPerRoute(maxRouteConnections);
    connectionManager.setValidateAfterInactivity(5000);

    httpClient = HttpClients.custom()
        .setDefaultRequestConfig(
            RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(readTimeout)
                .setConnectionRequestTimeout(DEFAULT_CONNECT_REQUEST_TIMEOUT).build())
        .setConnectionManager(connectionManager).evictIdleConnections(2, TimeUnit.MINUTES)
        .evictExpiredConnections().build();
    return this;
  }

  public String get(String url, Map<String, String> paramsMap) throws IOException {
    HttpEntity responseEntity = null;
    try {
      List<NameValuePair> nameValuePairs = HttpUtils.getByMap(paramsMap);
      String queryString = EntityUtils.toString(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
      HttpGet httpGet = new HttpGet(String.format("%s?%s", url, queryString));

      HttpResponse response = httpClient.execute(httpGet);
      responseEntity = response.getEntity();
      String content = "";
      if (Objects.nonNull(responseEntity)) {
        content = EntityUtils.toString(responseEntity, "UTF-8");
      }
      return content;
    } finally {
      if (Objects.nonNull(responseEntity)) {
        EntityUtils.consume(responseEntity);
      }
    }
  }

  public String post(String url, Map<String, String> paramsMap) throws IOException {
    HttpEntity responseEntity = null;
    try {
      List<NameValuePair> nameValuePairs = HttpUtils.getByMap(paramsMap);
      HttpPost httpPost = new HttpPost(url);
      httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));

      HttpResponse response = httpClient.execute(httpPost);
      responseEntity = response.getEntity();
      String content = "";
      if (Objects.nonNull(responseEntity)) {
        content = EntityUtils.toString(responseEntity, "UTF-8");
      }
      return content;
    } finally {
      if (Objects.nonNull(responseEntity)) {
        EntityUtils.consume(responseEntity);
      }
    }
  }

}
